<template>
  <el-card shadow="always" :body-style="{ padding: '20px' }">
    <template v-slot:header>
      <el-button type="primary" size="default" icon="ele-Plus" @click="showAddDialog">添加</el-button>
    </template>

    <!-- element-plus当中表格和html当中的表格不一样
    以列为单位，el-table-column代表表格的列，表格有几列就复制几个
    table身上会有一些属性： 
      data属性专门用于往table当中传递动态数据，而且这个数据必须是对象的数组
        data的数据一旦给上，默认会把data的数据给每个列都传递一份
        data的数据传递给每个列，每个列的内部都是在展示这个数据  vfor
        每个列的内部在遍历展示数据的时候，如果需要额外的结构和样式，内部说了不算，而是外部说了算
      border 边框，如果有边框就加上，如果不要边框就不要
      stripe 代表斑马状  如果你需要就加 不需要就不加
    column身上也会有一些属性
      type 代表这个列的类型  type的值为index，代表序号列
      align 代表列当中内容对其方式  align：center
      width 代表列的宽度  注意宽度在写的时候没有px 直接写数字，就代表了多少px
            如果不设置width，那么所有的列平分天下
      prop  代表后续这一列在显示动态数据的时候，显示的是对象的哪个属性
      label 代表列名
   -->
    <el-table :data="trademarkList" border stripe>
      <el-table-column type="index" align="center" width="80" label="序号"></el-table-column>
      <el-table-column label="品牌名称" prop="tmName"></el-table-column>
      <el-table-column label="品牌LOGO">
        <!-- 这里是作用域插槽的使用 -->
        <template v-slot="{row}">
          <img :src="row.logoUrl" alt="" style="width: 100px;height: 60px;">
        </template>
      </el-table-column>
      <el-table-column label="操作">
        <!-- 使用作用域插槽，目的是为了知道后期修改删除的是哪个row -->
        <template v-slot="{row}">
          <el-button type="warning" size="small" icon="ele-Edit" @click="showUpdateDialog(row)">修改</el-button>
          <el-button type="danger" size="small" icon="ele-Delete" @click="deleteTrademark(row)">删除</el-button>
        </template>
      </el-table-column>
    </el-table>
    
    <!--  @size-change="handleSizeChange"
       -->
      <!-- 
        1、当前页
        2、每页数量
        3、总条数
        4、连续数
        配个事件  切换页码的事件
       -->
    <el-pagination
      @current-change="getTrademarkList"
      @size-change="handleSizeChange"
      style="margin-top:20px"
      v-model:current-page="page"
      v-model:page-size="limit"
      :total="total"
      :pager-count="9"
      :page-sizes="[3,5,7,10]"
      layout=" prev, pager, next, jumper,->,sizes,total"
    />


    <el-dialog v-model="dialogFormVisible" :title="`${tmForm.id?'修改品牌':'添加品牌'}`">
      <!-- :model="tmForm主要是用来做表单验证用的，只要是做表单验证，必须要写上这个
      否则，验证规则和收集的数据对象，没有联系，也就没法去正确进行规则的使用 -->
      <el-form style="width: 80%;" :rules="rules" :model="tmForm" ref="tmFormRef">
        <el-form-item label="品牌名称" label-width="100px" prop="tmName">
          <el-input v-model="tmForm.tmName" autocomplete="off" />
        </el-form-item>
        <el-form-item label="品牌LOGO" label-width="100px" prop="logoUrl">
          <el-upload
            class="avatar-uploader"
            action="/app-dev/admin/product/fileUpload"
            :show-file-list="false"
            :on-success="handleAvatarSuccess"
            :before-upload="beforeAvatarUpload"
          >
            <img v-if="tmForm.logoUrl" :src="tmForm.logoUrl" class="avatar" />
            <el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
            <template #tip>
              <div class="el-upload__tip">
                上传的图片必须是jpg且不能大于2M
              </div>
            </template>
          </el-upload>
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogFormVisible = false">取消</el-button>
          <el-button type="primary" @click="addOrUpdateTrademark" >
            确定
          </el-button>
        </span>
      </template>
    </el-dialog>

  </el-card>


  
  
</template>
<script lang="ts">
  import { defineComponent } from 'vue';
  export default defineComponent({
    name:'Trademark'
  })
</script>
<script lang="ts" setup>
import {ref,onMounted, nextTick} from 'vue'
import trademarkApi,{type TrademarkData} from '@/api/trademark'
import { ElMessage, ElMessageBox, type FormRules } from 'element-plus';
import { Plus } from '@element-plus/icons-vue'
import type { UploadProps } from 'element-plus'




// 功能1：搭建静态列表需要的数据及获取初始化动态数据列表
const page = ref(1)
const limit = ref(3)
const total = ref(0)
// ref是一个函数 这个函数在定义的时候，定义了泛型，这个泛型也是决定了ref函数返回值的类型
// 我们在使用调用ref函数的时候就可以确定它定义时候的泛型，你确定的类型就是返回值的类型
const trademarkList = ref<TrademarkData[]>([])
// 请求获取品牌列表
// 这个函数又在做函数又在做回调函数
// 第一次在mounted当中是做为函数调用
// 使用再切换页码的事件后面是作为回调使用
const getTrademarkList = async (num:number = 1) => {
  page.value = num
  try {
    const result = await trademarkApi.getPageList(page.value,limit.value)
    // console.log(result);
    trademarkList.value = result.records
    total.value = result.total
  } catch (error) {
    ElMessage.error('获取品牌列表失败')
  }
}
onMounted(() => {
  getTrademarkList()
})

// 处理切换页码
// const handleCurrentChange = (num:number) => {
//   page.value = num
//   getTrademarkList()
// }

// 处理切换每页的数量
// 这个函数不能和上面哪个一样，直接合并到请求的函数当中，因为参数是有顺序的
const handleSizeChange = (size:number) => {
  limit.value = size
  getTrademarkList()
}




// 功能2、添加的dialog需要的数据及添加收集数据的逻辑
const dialogFormVisible = ref(false)
// 上传组件使用的动态数据和函数
// const imageUrl = ref('')
const handleAvatarSuccess: UploadProps['onSuccess'] = (
  response,
  uploadFile
) => {
  // imageUrl.value = URL.createObjectURL(uploadFile.raw!)  //拿到的是本地路径，没用
  // console.log(response,uploadFile);
  // console.log(imageUrl.value);

  tmForm.value.logoUrl = response.data //这个才是收集我们上传成功的网络路径

}
// 对上传的文件进行格式和大小的限制
const beforeAvatarUpload: UploadProps['beforeUpload'] = (rawFile) => {
  if (rawFile.type !== 'image/jpeg') {
    ElMessage.error('图片必须是jpg格式')
    return false
  } else if (rawFile.size / 1024 / 1024 > 2) {
    ElMessage.error('图片的大小不能超过2MB!')
    return false
  }
  return true
}

// 点击添加按钮，显示对话框
const showAddDialog = () => {
  dialogFormVisible.value = true

  // 清空一下子dialog当中的内容,解决添加完取消，再次点击添加数据依然存在的问题
  tmForm.value = {
    tmName:'',
    logoUrl:''
  }
  // 等待dom更新完成后，执行操作
  nextTick(() => {
    // 清除表单验证的结果
    tmFormRef.value.resetFields()
  })
}

// 添加品牌需要收集一个品牌对象，那么我们要考虑这些事********************************
// 1、收集什么
    // 收集的东西要看接口文档当中参数需要什么东西，需要什么我们就朝这个目标去收集
    // {
    //   tmName,
    //   logoUrl
    // }
// 2、收集到哪
      // 需要自己定义一个对象去收集
// 3、怎么收集
      // 看你写的结构来决定  如果是表单元素，我们一般用的v-model，如果不是，那么我们可能要写逻辑去收集

// 定义收集品牌的对象
const tmForm = ref<TrademarkData>({
  tmName:'',
  logoUrl:''
})




// 功能3、修改的收集数据逻辑
// 点击修改按钮
const showUpdateDialog = (row:TrademarkData) => {
  dialogFormVisible.value = true
  // tmForm.value = row
  // 拷贝  --》 数据拷贝
  // 拷贝的特点： 堆当中必须出现新的空间地址才叫拷贝
  // 下面两个都不会拷贝
  // var a = 10
  // var b = a

  // var obj = {m:100}
  // var obj1 = obj

  // 深浅拷贝说的是对象当中的数据
  // 如果对象当中还有对象数据，拷贝后地址值不变，叫浅拷贝
  // 如果对象当中还有对象数据，拷贝后地址值改变，叫深拷贝
  // 如果对象当中没有对象数据，直接浅拷贝即可

  tmForm.value = {...row} //解决修改tmForm的时候，row的数据也在跟着改变的bug
}




// 功能4、添加和修改的确认发请求逻辑

// 点击确认按钮，发请求
const addOrUpdateTrademark = () => {

  // 表单验证整体校验的逻辑,需要调用form组件对象的validate方法去做
  tmFormRef.value.validate(async (isValid:boolean) => {
    if(isValid){
      // 1、获取请求参数  tmForm
      let trademark = tmForm.value
      // 2、整理参数  需要整理就整理，如果直接就是后台要的数据格式，就不需要整理
      // 3、发请求
      try {
        await trademarkApi.addOrUpdate(trademark)
        // 4、成功干啥
        ElMessage.success(trademark.id?'修改品牌成功':'添加品牌成功')
        dialogFormVisible.value = false
        getTrademarkList(trademark.id?page.value:1)
      } catch (error) {
        // 5、失败干啥
        ElMessage.error(trademark.id?'修改品牌失败':'添加品牌失败')
        dialogFormVisible.value = false
      }
    }
  })
}


// 功能5、删除品牌的逻辑
// 点击删除按钮逻辑
const deleteTrademark = (row:TrademarkData) => {
  ElMessageBox.confirm(
    `你确定要删除${row.tmName}吗？`,
    'Warning',
    {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning',
    }
  )
  // messagebox返回的也是一个promise，这个promise是内部封装过的
  // .then代表的是成功的回调，在这代表的是点击确认的逻辑
  // .catch代表的是失败的回调，在这代表的是点击取消的逻辑
    .then(async () => {
      try {
        await trademarkApi.delete(row.id as number)
        ElMessage({
          type: 'success',
          message: '删除品牌成功',
        })
        // 如果删除的当前页数量是大于1，那么删除后还是停留在当前页
        // 如果当前页数量不大于1就是1，那么删除后是要停留在上一页
        getTrademarkList(trademarkList.value.length > 1?page.value:page.value - 1)
      } catch (error) {
        ElMessage({
          type: 'error',
          message: '删除品牌失败',
          duration:5000
        })
      }
      
    })
    .catch(() => {
      ElMessage({
        type: 'info',
        message: '取消删除成功',
      })
    })
}




// 功能6、表单的验证
// 这个rules定义的就是我们要的验证规则
// 这些规则都是内置的规则
// 一个属性对应一个规则数组，规则数组当中每个规则都是一个对象
// 每个规则对象包含三种属性，1、内置规则  2、报错信息  3、触发方式
// 触发方式包含3种：1、失去焦点  2、修改的时候  3、整体校验的时候
// 单个校验（在输入某个数据的时候只对这一个进行校验）    整体校验（点击确定的时候对所有的进行校验）


// 自定义验证规则的函数
const validateTmName = (rule: any, value: any, callback: any) => {
  if(value.length < 2 || value.length > 10){
    callback(new Error('品牌名称必须2-10')) //callback在调用的时候传递错误信息 代表验证不通过
  }else{
    callback() //验证用过
  }
}

const rules = ref<FormRules>({
  tmName: [
    { required: true, message: '品牌名称必须填写', trigger: 'blur' },
    // { min: 2, max: 10, message: '品牌名称长度必须在2-10', trigger: 'change' },
    { validator: validateTmName, trigger: 'change' }

  ],

  // 这个upload组件在做表单验证的时候，只有整体校验才能触发
  logoUrl: [
    {
      required: true,
      message: '品牌图片必须上传',
      trigger: 'change',
    },
  ]
})

// tmFormRef拿到表单的组件对象
const tmFormRef = ref()

</script>

<style scoped>
.avatar-uploader .avatar {
  width: 178px;
  height: 178px;
  display: block;
}
</style>

<style>
.avatar-uploader .el-upload {
  border: 1px dashed var(--el-border-color);
  border-radius: 6px;
  cursor: pointer;
  position: relative;
  overflow: hidden;
  transition: var(--el-transition-duration-fast);
}

.avatar-uploader .el-upload:hover {
  border-color: var(--el-color-primary);
}

.el-icon.avatar-uploader-icon {
  font-size: 28px;
  color: #8c939d;
  width: 178px;
  height: 178px;
  text-align: center;
}
</style>
